/*
 * EscritorIndce.cpp
 *
 *  Created on: 29/10/2011
 *      Author: diego
 */

#include "IndexWriter.h"

IndexWriter::IndexWriter(string prefijo, int n) {
	Configuracion* conf = Configuracion::getConf(PATH_CONF);
	string path = conf->path_indice() + prefijo + "_indice.dat";
	this->indice = new ofstream(path.c_str(), ios::app | ios::binary);

	path = conf->path_indice() + prefijo + "_terminos.dat";
	this->terminos = new ofstream(path.c_str(), ios::app);

	path = conf->path_indice() + prefijo + "_header.dat";
	this->header = new ofstream(path.c_str(), ios::app | ios::binary);

	path = conf->path_indice() + prefijo + "_docs.dat";
	this->docs = new BitWriter(path.c_str());

	this->cont_registros = 0;

	this->compresorTerminos = new FrontCoding(n);
}


IndexWriter::IndexWriter(int n){
	Configuracion* conf = Configuracion::getConf(PATH_CONF);
	string path = conf->path_indice() + "indice.dat";
	this->indice = new ofstream(path.c_str(), ios::app | ios::binary);

	path = conf->path_indice() + "terminos.dat";
	this->terminos = new ofstream(path.c_str(), ios::app);

	path = conf->path_indice() + "header.dat";
	this->header = new ofstream(path.c_str(), ios::app | ios::binary);

	path = conf->path_indice() + "docs.dat";
	this->docs = new BitWriter(path.c_str());

	this->cont_registros = 0;

	this->compresorTerminos = new FrontCoding(n);
}

void IndexWriter::write(super_reg* reg){
	this->cont_registros++;

	reg_indice_fijo reg_indice;
	reg_docs_variable reg_docs;

	string* termino = new string(reg->termino);
	int repetidos = this->compresorTerminos->comprimir(termino);

	reg_indice.offset_terminos = this->terminos->tellp();
	reg_indice.offset_docs = this->docs->getPosition();

//	if (termino->length() + 1 > 100 || termino->length() + 1 < 0){
//		cout << reg.termino << endl;
//	}

	reg_indice.distintos = termino->length() + 1;
	//cout << reg_indice.distintos << endl;
	reg_indice.repetidos = repetidos;
	reg_indice.cant_docs = reg->cant_docs;
	reg_indice.frec_t = reg->frec_t;

	this->indice->write(reinterpret_cast<char *>(&reg_indice), sizeof(reg_indice_fijo));

	this->indice->flush();

	this->terminos->write(termino->c_str(), termino->length() + 1);

	IteradorLista<reg_docs_variable*> it = reg->lista->iterador();
	reg_docs_variable* nodo;
	reg_docs_variable* nodo_anterior = NULL;

	while (it.tieneSiguiente()) {
		nodo = it.siguiente();

		// DEBUG
		//cout << "(" << nodo->doc_id << ", " << nodo->frec << ");";

		// guardo la lista de distancias
		if (nodo_anterior != NULL){
			reg_docs.doc_id = nodo->doc_id - nodo_anterior->doc_id;
		}else{
			reg_docs.doc_id = nodo->doc_id;
		}


		reg_docs.frec = nodo->frec;

		//Grabo los datos con codigos delta
		deltaEncode(reg_docs.doc_id, this->docs);
		deltaEncode(reg_docs.frec, this->docs);

		// DEBUG
		//cout << "(" <<reg_docs.doc_id << ", " << reg_docs.frec << ");";

		nodo_anterior = nodo;
	}


	delete termino;
}

void IndexWriter::close(){

	reg_header_indice header;
	//cout << "cantidad de registros " << this->cont_registros << endl;
	header.cant_registros = this->cont_registros;
	this->header->write(reinterpret_cast<char *>(&header), sizeof(reg_header_indice));
	this->header->close();

	if (this->indice != NULL){
		this->indice->close();
	}

	if (this->terminos != NULL){
		this->terminos->close();
	}

	if (this->docs != NULL){
		this->docs->cerrar();
	}

}

IndexWriter::~IndexWriter() {
	if (this->indice != NULL){
		delete this->indice;
		this->indice = NULL;
	}

	if (this->terminos != NULL){
		delete this->terminos;
		this->terminos = NULL;
	}

	if (this->docs != NULL){
		delete this->docs;
		this->docs = NULL;
	}

	if (this->header != NULL){
		delete this->header;
		this->header = NULL;
	}

	delete this->compresorTerminos;
}

